/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package beans;

import facades.CandidateFacade;
import facades.UserFacade;
import facades.UserTokenFacade;
import entities.Candidate;
import entities.Company;
import entities.PublicRelations;
import entities.User;
import entities.UserToken;
import util.CookieHelper;
import util.Sha256Encrypter;
import javax.inject.Named;
import javax.enterprise.context.SessionScoped;
import java.io.Serializable;
import java.io.UnsupportedEncodingException;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.Date;
import java.util.Locale;
import java.util.ResourceBundle;
import java.util.UUID;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.enterprise.event.Event;
import javax.enterprise.event.Observes;
import javax.enterprise.event.TransactionPhase;
import javax.enterprise.inject.Produces;
import javax.faces.application.FacesMessage;
import javax.faces.context.FacesContext;
import javax.inject.Inject;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import qualifiers.HeaderClickedEvent;
import qualifiers.RecoveredPasswordEvent;
import qualifiers.CreatedEntityEvent;
import qualifiers.LoggedIn;

/**
 *
 * @author damfercer
 */
//TODO: Quitar todos los context.getApplication().evaluateExpressionGet y pasarlos a eventos.
@Named
@SessionScoped
public class LoginBean implements Serializable {
    @Inject
    @LoggedIn
    private Event<Company> loggedInCompanyEvent;
    @Inject
    @LoggedIn
    private Event<Candidate> loggedInCandidateEvent;
    @Inject
    @LoggedIn
    private Event<PublicRelations> loggedInPublicRelations;
    @Inject
    UserTokenFacade userTokenFacade;
    private String email;
    private String password;
    private User selectedUser;
    @Inject
    private UserFacade userEJB;
    @Inject
    CandidateFacade candidateEJB;
    @Inject
    @HeaderClickedEvent
    private Event<Integer> headerClickedEvent;
    private final String COOKIE_NAME="uTk";
    /**
     * Creates a new instance of LoginBean
     */
    public LoginBean() {
    }
    
    
    public String logIn() throws NoSuchAlgorithmException, UnsupportedEncodingException{
        password=Sha256Encrypter.getSha256(password);
        FacesContext context = FacesContext.getCurrentInstance();
        HttpServletResponse response = (HttpServletResponse)context.getExternalContext().getResponse();
        HttpServletRequest request = (HttpServletRequest)context.getExternalContext().getRequest();
        Locale locale=context.getViewRoot().getLocale();
        ResourceBundle rb = ResourceBundle.getBundle("messages", locale);
        try {
            email=email.toLowerCase();
            request.login(email, password);
        } 
        catch (ServletException e) {
            String loginError=rb.getString("LogInError");
            FacesMessage msg =new FacesMessage(loginError,loginError);
            msg.setSeverity(FacesMessage.SEVERITY_ERROR);
            context.addMessage(null, msg);
            context.renderResponse();
            return null;
        }   
        selectedUser=userEJB.getUserFromEmailAndPassword(email, password);
        if(selectedUser==null){
            String loginError=rb.getString("LogInError");
            FacesMessage msg =new FacesMessage(loginError,loginError);
            msg.setSeverity(FacesMessage.SEVERITY_ERROR);
            context.addMessage(null, msg);
            context.renderResponse();
        }
        else{
            userEJB.refresh(selectedUser);
            userEJB.evict(selectedUser, selectedUser.getIdUser());
            selectedUser=userEJB.find(selectedUser.getIdUser());
            Integer newLogins=selectedUser.getLogins() + 1;
            Date newDate=new Date();
            selectedUser.setLogins(newLogins);
            selectedUser.setLastDate(newDate);
            userEJB.edit(selectedUser);
            UserToken userToken=createToken();
            CookieHelper.addCookie(response, COOKIE_NAME, userToken.getToken(), 2592000); // Extends age.
            if(selectedUser.getCandidate()!=null){
                loggedInCandidateEvent.fire(selectedUser.getCandidate());
                return "/views/candidate/NewEditCandidateView?faces-redirect=true";
            }
            else if(selectedUser.getCompany()!=null){
                loggedInCompanyEvent.fire(selectedUser.getCompany());
                return "/views/company/NewEditCompanyView?faces-redirect=true";
            }
            else if(selectedUser.getUserType().getIdUserType().equals(3)){
                return "/views/admin/IndexViewAdmin?faces-redirect=true";
            }
            else if(selectedUser.getPublicRelations()!=null){
                loggedInPublicRelations.fire(selectedUser.getPublicRelations());
                return "/views/publicRelations/IndexViewPublicRelations?faces-redirect=true";
            }
        }
        return null;
    }
    /**
     * @return the email
     */
    public String getEmail() {
        return email;
    }

    /**
     * @param email the email to set
     */
    public void setEmail(String email) {
        this.email = email;
    }

    /**
     * @return the password
     */
    public String getPassword() {
        return password;
    }

    /**
     * @param password the password to set
     */
    public void setPassword(String password) {
        this.password = password;
    }

    /**
     * @return the selectedUser
     */
    public @Produces @LoggedIn User getSelectedUser() {
        return selectedUser;
    }

    /**
     * @param selectedUser the selectedUser to set
     */
    public void setSelectedUser(User selectedUser) {
        this.selectedUser = selectedUser;
    }
    
    public void invalidateSession(){
        FacesContext context = FacesContext.getCurrentInstance();
        HttpServletRequest request = (HttpServletRequest)context.getExternalContext().getRequest();
        try {
            request.logout();
            HttpSession session=(HttpSession)FacesContext.getCurrentInstance().getExternalContext().getSession(false);
            if(session!=null){
                session.invalidate();
            }
        } catch (ServletException ex) {
            Logger.getLogger(LoginBean.class.getName()).log(Level.SEVERE, null, ex);
        }
        
    }
        
    public String redirectCreateCandidate(){
        invalidateSession();
        return "/views/recruit/CreateCandidateView?faces-redirect=true";
    }
    public String redirectCreateCompany(){
        invalidateSession();
        return "/views/recruit/CreateCompanyView?faces-redirect=true";
    }
    
    public @Produces @LoggedIn Company logedCompany(){
        return selectedUser.getCompany();
    }
        
    public @Produces @LoggedIn Candidate logedCandidate() {
        return selectedUser.getCandidate();
    }
    
    public @Produces @LoggedIn PublicRelations logedPublicRelations(){
        return selectedUser.getPublicRelations();
    }
    
    public void onNewUser(@Observes @CreatedEntityEvent User u){
        selectedUser=u;
    }
    
    public void onNewCandidate(@Observes(during = TransactionPhase.AFTER_SUCCESS) @CreatedEntityEvent Candidate newCandidate) throws NoSuchAlgorithmException, UnsupportedEncodingException{
        selectedUser=newCandidate.getUser();
        FacesContext context = FacesContext.getCurrentInstance();
        HttpServletRequest request = (HttpServletRequest)context.getExternalContext().getRequest();
        HttpServletResponse response = (HttpServletResponse)context.getExternalContext().getResponse();
        Locale locale=context.getViewRoot().getLocale();
        ResourceBundle rb = ResourceBundle.getBundle("messages", locale);
        try {
            request.login(newCandidate.getUser().getEmail(), newCandidate.getUser().getPassword());
            UserToken userToken=createToken();
            CookieHelper.addCookie(response, COOKIE_NAME, userToken.getToken(), 2592000); // Extends age.        
        } 
        catch (ServletException e) {
            String loginError=rb.getString("LogInError");
            FacesMessage msg =new FacesMessage(loginError,loginError);
            msg.setSeverity(FacesMessage.SEVERITY_ERROR);
            context.addMessage(null, msg);
            context.renderResponse();
        }   
    }
    
//    public void onEditedUser(@Observes(during = TransactionPhase.AFTER_SUCCESS) @EditedEntityEvent User user){
//        this.selectedUser=user; 
//    }
//    public void onEditedCandidate(@Observes(during = TransactionPhase.AFTER_SUCCESS) @EditedEntityEvent Candidate candidate){
//        candidate.setUser(selectedUser);
//        this.selectedUser.setCandidate(candidate); 
//    }
//    public void onEditedCompany(@Observes(during = TransactionPhase.AFTER_SUCCESS) @EditedEntityEvent Company company){
//        company.setIdUser(selectedUser);
//        this.selectedUser.setCompany(company); 
//    }
    
    public void onRecoveredPassword(@Observes @RecoveredPasswordEvent User user){
        this.selectedUser=user;
        FacesContext context = FacesContext.getCurrentInstance();
        HttpServletRequest request = (HttpServletRequest)context.getExternalContext().getRequest();
        HttpServletResponse response = (HttpServletResponse)context.getExternalContext().getResponse();
        Locale locale=context.getViewRoot().getLocale();
        ResourceBundle rb = ResourceBundle.getBundle("messages", locale);
        try {
            request.login(user.getEmail(), user.getPassword());
            UserToken userToken=createToken();
            CookieHelper.addCookie(response, COOKIE_NAME, userToken.getToken(), 2592000); // Extends age.
            
        } 
        catch (ServletException e) {
            String loginError=rb.getString("LogInError");
            FacesMessage msg =new FacesMessage(loginError,loginError);
            msg.setSeverity(FacesMessage.SEVERITY_ERROR);
            context.addMessage(null, msg);
            context.renderResponse();
        }   
    }
    
    public void onNewcompany(@Observes(during = TransactionPhase.AFTER_SUCCESS) @CreatedEntityEvent Company company){
        this.selectedUser=company.getIdUser();
        FacesContext context = FacesContext.getCurrentInstance();
        HttpServletRequest request = (HttpServletRequest)context.getExternalContext().getRequest();
        HttpServletResponse response = (HttpServletResponse)context.getExternalContext().getResponse();
        Locale locale=context.getViewRoot().getLocale();
        ResourceBundle rb = ResourceBundle.getBundle("messages", locale);
        try {
            request.login(company.getIdUser().getEmail(), company.getIdUser().getPassword());
            UserToken userToken=createToken();
            CookieHelper.addCookie(response, COOKIE_NAME, userToken.getToken(), 2592000); // Extends age.
            
        } 
        catch (ServletException e) {
            String loginError=rb.getString("LogInError");
            FacesMessage msg =new FacesMessage(loginError,loginError);
            msg.setSeverity(FacesMessage.SEVERITY_ERROR);
            context.addMessage(null, msg);
            context.renderResponse();
        }   
    }
    
    public Boolean getIsLoggedIn(){
        Boolean res=false;
        if((selectedUser!=null && selectedUser.getCandidate()!=null) || (selectedUser!=null && selectedUser.getCompany()!=null) || (selectedUser!=null && selectedUser.getUserType().getIdUserType()==3) || (selectedUser!=null && selectedUser.getPublicRelations()!=null)){
            res=true;
        }
        return res;
    }
    
    public String goIndex(){
        if(selectedUser!=null && selectedUser.getCandidate()!=null){
            headerClickedEvent.fire(0);
            //return "/views/candidate/IndexViewCandidate?faces-redirect=true";
            return "/views/candidate/NewEditCandidateView?faces-redirect=true";

        }
        else if(selectedUser!=null && selectedUser.getCompany()!=null){
            headerClickedEvent.fire(0);
            //return "/views/company/IndexViewCompany?faces-redirect=true";
            //return "/views/company/search/NewSearchListView?faces-redirect=true";
            return "/views/company/NewEditCompanyView?faces-redirect=true";
        }
        else if(selectedUser!=null && selectedUser.getUserType().getIdUserType().equals(3)){
            return "/views/admin/IndexViewAdmin?faces-redirect=true";
        }
        else if(selectedUser!=null&& selectedUser.getPublicRelations()!=null){
            headerClickedEvent.fire(0);
            loggedInPublicRelations.fire(selectedUser.getPublicRelations());
            return "/views/publicRelations/IndexViewPublicRelations?faces-redirect=true";
        }
        else{
            return "/index?faces-redirect=true";
        }
    }
    
    public String redirectIndex(){
        String redirect=null;
        if(selectedUser!=null && selectedUser.getCandidate()!=null){
            headerClickedEvent.fire(0);
            loggedInCandidateEvent.fire(selectedUser.getCandidate());
            //redirect= "/views/candidate/IndexViewCandidate?faces-redirect=true";
            redirect= "/views/candidate/NewEditCandidateView?faces-redirect=true";

        }
        else if(selectedUser!=null && selectedUser.getCompany()!=null){
            headerClickedEvent.fire(0);
            loggedInCompanyEvent.fire(selectedUser.getCompany());
            //redirect= "/views/company/IndexViewCompany?faces-redirect=true";
            //redirect= "/views/company/search/NewSearchListView?faces-redirect=true";
            return "/views/company/NewEditCompanyView?faces-redirect=true";
        }
        else if(selectedUser!=null && selectedUser.getUserType().getIdUserType().equals(3)){
            return "/views/admin/IndexViewAdmin?faces-redirect=true";
        }
        else if(selectedUser!=null&& selectedUser.getPublicRelations()!=null){
            headerClickedEvent.fire(0);
            loggedInPublicRelations.fire(selectedUser.getPublicRelations());
            return "/views/publicRelations/IndexViewPublicRelations?faces-redirect=true";
        }
        else{
            FacesContext context = FacesContext.getCurrentInstance();
            HttpServletRequest request = (HttpServletRequest)context.getExternalContext().getRequest();
            HttpServletResponse response = (HttpServletResponse)context.getExternalContext().getResponse();
            String uuid = CookieHelper.getCookieValue(request, COOKIE_NAME);
            if (uuid != null) {
                //System.out.println("Encuentra cookie");
                User user = userTokenFacade.findByToken(uuid);
                if (user != null) {
                    //System.out.println("Encuentra user");
                    try {
                        userEJB.evict(user, user.getIdUser());
                        userEJB.refresh(user);
                        user = userEJB.find(user.getIdUser());
                        request.login(user.getEmail(), user.getPassword());
                        this.selectedUser=user;
                        Integer newLogins=selectedUser.getLogins() + 1;
                        Date newDate=new Date();
                        selectedUser.setLogins(newLogins);
                        selectedUser.setLastDate(newDate);
                        userEJB.edit(selectedUser);
                        CookieHelper.addCookie(response, COOKIE_NAME, uuid, 2592000); // Extends age.
                        redirect=redirectIndex();
                    } catch (ServletException ex) {
                        CookieHelper.removeCookie(response, COOKIE_NAME);
                        Locale locale=context.getViewRoot().getLocale();
                        ResourceBundle rb = ResourceBundle.getBundle("messages", locale);
                        String loginError=rb.getString("LogInError");
                        FacesMessage msg =new FacesMessage(loginError,loginError);
                        msg.setSeverity(FacesMessage.SEVERITY_ERROR);
                        context.addMessage(null, msg);
                        context.renderResponse();
                    }
                } else {
                    CookieHelper.removeCookie(response, COOKIE_NAME);
                }
            }
        }
        return redirect;
    }
    
    public String logout(){
        FacesContext context = FacesContext.getCurrentInstance();
        HttpServletResponse response = (HttpServletResponse)context.getExternalContext().getResponse();
        userTokenFacade.removeAllUserToken(selectedUser);
        CookieHelper.removeCookie(response, COOKIE_NAME);
        if(selectedUser.getCandidate()!=null){
            candidateEJB.evict(selectedUser.getCandidate(),selectedUser.getCandidate().getIdCandidate());
        }
        invalidateSession();
        return "/index?faces-redirect=true";
    }
    
    public UserToken createToken(){
        String uuid = UUID.randomUUID().toString();
        UserToken userToken= new UserToken();
        userToken.setCreationDate(new Date());
        userToken.setUser(selectedUser);
        userToken.setToken(uuid);
        userTokenFacade.create(userToken);
        if(this.selectedUser.getUserTokenCollection()==null){
            this.selectedUser.setUserTokenCollection(new ArrayList<UserToken>());
        }
        this.selectedUser.getUserTokenCollection().add(userToken);
        return userToken;
    }
}
